import ij.IJ;
import ij.ImagePlus;
import ij.gui.NewImage;
import ij.plugin.PlugIn;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.Scanner;

import pluginUtils.Doublet;
import pluginUtils.Punkt;
import pluginUtils.Quadrilatere;
import pluginUtils.Transformation;


// Read a datafile and a image file, compute the distorted image 
// for anamorphosis inside a cylinder
// The mirror is concave spherical


public class AnamorphSphereCreuseAnalytic extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	
	
	private ImageProcessor primeIP; 
	private int X=2800,Y=2100; // image size
	
	private ImagePlus inverted;  
	private ImageProcessor inv_ip;  
	
	
	
	
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	


	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	
	
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu;
		 
	}
	
	private void drawPoint(Punkt p){
		double xCenter=p.getY(); 
		double yCenter=p.getZ(); 
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		primeIP.fillOval(intX-10,intY-10,20,20);
	}
	private void drawPoint(Punkt p,ImageProcessor toto){
		double xCenter=p.getY(); 
		double yCenter=p.getZ(); 
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		System.out.println(intX+" ** "+intY);
		toto.fillOval(intX-5,intY-5,10,10);
	}
	
	private void drawLine(double xd,double yd,double xf,double yf,ImageProcessor toto){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		//System.out.println("---->"+XD+" "+YD+" "+XF+" "+YF); 
		toto.drawLine(XD,YD,XF,YF); 
	}
	
	
	private void drawLine(Punkt A,Punkt B,ImageProcessor toto){
		drawLine(A.getY(),A.getZ(),B.getY(),B.getZ(),toto); 
	}
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		//System.out.println("---->"+XD+" "+YD+" "+XF+" "+YF); 
		primeIP.drawLine(XD,YD,XF,YF); 
	}
	
	private void drawLine(Punkt A,Punkt B){
		drawLine(A.getY(),A.getZ(),B.getY(),B.getZ()); 
	}
	
	
	
	
	
	public void run(String arg) {
		System.out.println("go");
		
	
		
		//ImagePlus imp = IJ.openImage("/tmp/Mona_Lisa.jpg");
		ImagePlus imp=IJ.openImage("F:/Povray/anamorphoses/Mona_Lisa.png");
		//ImagePlus imp=IJ.openImage("F:/Povray/anamorphoses/snail.png");
		//ImagePlus imp=IJ.openImage("C:/Utilisateurs/Public/Images publiques/snail.png");
		//ImagePlus imp=IJ.openImage("C:/Documents and Settings/Francesco/Mes documents/Mona_Lisacarre.png");

		imp.setTitle("PrimeIP");
		
	
		System.out.println(imp); 
		primeIP=imp.getProcessor();
		X=primeIP.getWidth(); 
		Y=primeIP.getHeight(); 
		
        setStack(null, imp.getStack());
        setCalibration(imp.getCalibration()); 
		
        	show();
		
		
		

		

		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.RED);
		primeIP.setLineWidth(10); 
	
		setProcessor("Verifying", primeIP);
		
		
		
		 
		
             
          // create a new image of size (2h)*(2piR)
		int W=2000; 
		int H=3000; 
 			inverted = NewImage.createRGBImage ("Inverted image",W,H, 1, NewImage.FILL_BLACK);
   
             
 			inv_ip = inverted.getProcessor();
 			
 			for(int i=0;i<inverted.getWidth();i++)
 				for(int j=0;j<inverted.getHeight();j++)
 					inv_ip.putPixel(i,j,0xFFFFFF); 
     
 			
 			
 			// cylinder diameter
 			double l=4; 
 			// Radius of the carving sphere
 			double R=6;
 			double n=10; //50.0; 
 			double coefAngle=W/(2*Math.PI);
 			double coefA=W/(2*Math.PI*l); 
 			double radic=Math.sqrt(R*R-l*l);
 			double coefB=coefA*radic; 
 			for(int i=0;i<primeIP.getWidth();i++){
 				//double X1=(i-primeIP.getWidth()/2.0)/primeIP.getWidth();
 				double X1=2.0*i/primeIP.getWidth()-1; 
 				for(int kl=0;kl<n;kl++){
 					double X1p=X1+2.0*kl/(n*primeIP.getWidth());
 				for(int j=0;j<primeIP.getHeight();j++){
 					double Y1=2.0*j/primeIP.getHeight()-1;
 					for(int k=0;k<n;k++){
 					double Y1p=Y1+2.0*k/(n*primeIP.getHeight());	
 					double u=Math.sqrt(X1p*X1p+Y1p*Y1p);
 					if(u>1) continue;
 					u=u*l;
 					double alpha=Math.atan2(X1p,Y1p); 
 					alpha=alpha+Math.PI; 
 					//System.out.println(alpha*180/Math.PI); 
 					double Nx=alpha*coefAngle;
 					double foncU=(l+u)*(R*R-2*u*u)/(2*u*Math.sqrt(R*R-u*u))-Math.sqrt(R*R-u*u); 
 					double Ny=coefA*foncU+coefB;
 					int col=primeIP.getPixel(i,j); 
 					inv_ip.putPixel((int)Nx,(int)Ny,col);
 					}// for k 
 				}// for j
 				} // for kl	
 			}// for i
        
      
	
		inverted.show();
		
		System.out.println("end !");
	
		
		}
	}	

	